package com.cqhfan.imservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqhfan.api.clients.content.WorksClient;
import com.cqhfan.api.clients.user.FollowClient;
import com.cqhfan.api.clients.user.UserClient;
import com.cqhfan.core.enums.MessageTypeEnum;
import com.cqhfan.core.exceptions.BizException;
import com.cqhfan.core.utils.UuidContextHolder;
import com.cqhfan.imservice.handler.UserConnectionSession;
import com.cqhfan.imservice.mapper.SystemMessageMapper;
import com.cqhfan.imservice.service.SystemMessageService;
import com.cqhfan.pojo.content.po.Works;
import com.cqhfan.pojo.im.dto.SystemMessageDTO;
import com.cqhfan.pojo.im.dto.WebSocketMessageDTO;
import com.cqhfan.pojo.im.dto.WebSocketSystemMessageDTO;
import com.cqhfan.pojo.im.po.SystemMessage;
import com.cqhfan.pojo.user.po.User;
import com.cqhfan.redis.constants.RedisConstants;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

/**
 * @author 眭传洪
 * @create 2025-08-16 2:18
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SystemMessageServiceImpl extends ServiceImpl<SystemMessageMapper, SystemMessage> implements SystemMessageService {

    private final FollowClient followClient;

    private final UserClient userClient;

    private final WorksClient worksClient;

    private final StringRedisTemplate stringRedisTemplate;

    @Override
    public void listenSystemMessageSend(SystemMessageDTO message) {
        // 判断幂等性 这里其实可以考虑一下用lua脚本，把判断key和删除标志原子性执行，不然有可能会出现问题！！！
        String uuid = message.getUuid();
        String key = RedisConstants.IM.SYSTEM_MESSAGE_IDEMPOTENT_KEY_PREFIX + uuid;
        Boolean hasKey = stringRedisTemplate.hasKey(key);
        if (BooleanUtil.isFalse(hasKey)) {
            // 已经处理过
            return;
        }
        // 删除幂等性标志
        stringRedisTemplate.delete(key);

        // 转换消息
        SystemMessage systemMessage = BeanUtil.copyProperties(message, SystemMessage.class);
        systemMessage.setIfRead(Boolean.FALSE);
        systemMessage.setCreateTime(LocalDateTime.now());
        save(systemMessage);

        // 通过websocket推送消息（只有朋友才需要）
        Long senderUserId = message.getSenderUserId();
        Long receiveUserId = message.getReceiveUserId();
        // 存储登录uuid
        UuidContextHolder.setUuid(message.getLoginUuid());
        List<Long> friendUserIds = followClient.listFriend(senderUserId);
        if (!friendUserIds.contains(receiveUserId)) {
            return;
        }
        // 查询发送人信息
        List<User> users = userClient.listByIds(Collections.singletonList(senderUserId));
        if (CollUtil.isEmpty(users)) {
            throw new BizException("用户信息查询失败");
        }
        User user = users.get(0);
        // 查询作品信息
        Long worksId = message.getWorksId();
        Long commentId = message.getCommentId();
        Works works = worksClient.getByWorksId(worksId);
        if (works == null) {
            return;
        }
        // 构建消息
        WebSocketSystemMessageDTO systemMessageDTO = new WebSocketSystemMessageDTO();
        systemMessageDTO.setMessageType(message.getMessageType());
        systemMessageDTO.setWorksId(worksId);
        systemMessageDTO.setVideoCover(works.getCover());
        systemMessageDTO.setCommentId(commentId);
        WebSocketMessageDTO webSocketMessage = WebSocketMessageDTO.builder()
                .messageType(MessageTypeEnum.SYSTEM_MESSAGE.getValue())
                .senderId(senderUserId)
                .receiverId(receiveUserId)
                .content(message.getContent())
                .senderUserNickName(user.getNickName())
                .senderUserAvatar(user.getAvatar())
                .systemMessage(systemMessageDTO)
                .build();

        // 发送消息
        WebSocketSession session = UserConnectionSession.getConnectionRelation(receiveUserId);
        if (session == null || !session.isOpen()) {
            return;
        }
        try {
            session.sendMessage(new TextMessage(JSONUtil.toJsonStr(webSocketMessage)));
        } catch (IOException e) {
            throw new BizException(e.getMessage());
        }
    }

}
